home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / pcw.zip / TMENU.C < prev    next >
C/C++ Source or Header  |  1991-12-17  |  16KB  |  372 lines

  1. /**********************************************************/
  2. /* File Id.                  Tmenu.C                      */
  3. /* Author.                   Chris Balthrop               */
  4. /*         from Lmenu.c by   Stan Milam.                  */
  5. /* Date Written.             09oct91                      */
  6. /*                                                        */
  7. /*                                                        */
  8. /* Comments:  The routines in this file allow the creation*/
  9. /* and use of Top line style menus.  Moreover, more than  */
  10. /* one Top menu per window is allowed. More than one menu */
  11. /* can be stacked into one window.  The Mouse can be used */
  12. /* to make selection and scroll the menus or the arrow &  */
  13. /* PgDn/PgUp keys can be used.  Home & End keys move to   */
  14. /* first and last menus respectively.                     */
  15. /**********************************************************/
  16.  
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <conio.h>
  21. #include "pcw.i"
  22. #include "pcwproto.h"
  23. #include "keys.h"
  24. #include "menu.h"
  25.  
  26. #define MSGROW  2
  27. #define ITEMROW 1
  28.  
  29. /* Prototype the internal functions */
  30.  
  31. static void change_menu(TMNUTYPE *menu);
  32. static void change_bar_pos(TMNUTYPE *menu, int crnt_bar);
  33. static int  search_menu(TMNUTYPE *menu, int select_char);
  34. static int  search_mouse_select(TMNUTYPE *menu, int col);
  35. static int  get_max_bars(TMNUFLDS *ttmp);
  36.  
  37. /***********************************************************/
  38. /*                        Maketmenu                        */
  39. /*                                                         */
  40. /* This function when invoked will draw the Top style menu */
  41. /* pointed to by *menu.  See the TMNUTYPE definition in    */
  42. /* menu.h.                                                 */
  43. /***********************************************************/
  44.  
  45. WNDPTR *maketmenu(TMNUTYPE *menu) {
  46.  
  47.     MENU_WND    *twnd;            /* Pointer to menu window */
  48.  
  49.     twnd = &menu->twnd;           /* Establish adressablity */
  50.     setborder(twnd->btype);       /* Set borders & colors */
  51.     titlecolor(twnd->tfclr, twnd->tbclr);
  52.     bordercolor(twnd->bfclr, twnd->bbclr);
  53.  
  54.     /* Frame the menu window and store handle in menu structure */
  55.     twnd->wnd = wframe(twnd->urow, twnd->ucol,
  56.                        twnd->lrow, twnd->lcol,
  57.                        twnd->fcolor, twnd->bcolor);
  58.  
  59.     /* Check to see of okay */
  60.     if (twnd->wnd == NULL) return(NULL);
  61.  
  62.     /* Wframe may have adjusted boundries */
  63.     twnd->urow = twnd->wnd->urow;
  64.     twnd->ucol = twnd->wnd->ucol;
  65.     twnd->lrow = twnd->wnd->lrow;
  66.     twnd->lcol = twnd->wnd->lcol;
  67.  
  68.     /* Draw the arrows */
  69.     qputchar(twnd->urow+1,twnd->ucol,twnd->bfclr,twnd->bbclr,24);
  70.     qputchar(twnd->urow+1,twnd->lcol,twnd->bfclr,twnd->bbclr,25);
  71.  
  72.     /* Title wnd, Fill window with menu contents & return */
  73.     wtitle(twnd->wnd, twnd->tvloc, twnd->thloc, twnd->title);
  74.     change_menu(menu);
  75.     return(twnd->wnd);
  76. }
  77.  
  78. /***********************************************************/
  79. /*                        TmenuInput                       */
  80. /*                                                         */
  81. /* When invoked will manipulate Top style menu.  Returns   */
  82. /* the select_key in the TMNUFLDS.                         */
  83. /***********************************************************/
  84.  
  85. int tmenuinput(TMNUTYPE *menu) {
  86.  
  87.    TMNUFLDS       *ttmp, **stmp;       /* Pointers to menus */
  88.    MENU_WND       *twnd;          /* Pointer the menu parms */
  89.    int ch;                        /* For keyin() function */
  90.    int max_bars, max_menus;        /* How many menus & bars */
  91.    int crnt_wnd, crnt_bar;       /* Keep track menus & bars */
  92.    int row, col, bstatus;                      /* For Mouse */
  93.  
  94.    stmp = (TMNUFLDS **) menu->tlist;
  95.    ttmp = stmp[menu->wnd_pos];    /* Get address of 1st menu */
  96.    twnd = &menu->twnd;           /* Get address of wnd parms */
  97.  
  98.    if (mpresent) hide_mouse();      /* Turn the mouse off so */
  99.    re_order(twnd->wnd,NORMAL); /* We can reorder the windows */
  100.    if (mpresent) show_mouse();     /* And finally turn it on */
  101.    for (max_menus = 0;stmp[max_menus] != NULL;max_menus++);
  102.    max_menus--;                                /* and adjust */
  103.    max_bars  = get_max_bars(ttmp); /* Get # selects this menu */
  104.    if (mpresent) show_mouse();          /* Turn on the mouse */
  105.  
  106.    for(;;) {                                 /* Loop forever */
  107.       crnt_bar = menu->bar_pos;     /* Track current bar pos */
  108.       crnt_wnd = menu->wnd_pos;         /* And menu position */
  109.  
  110.       ch = keyin();
  111.       switch (ch) {                           /* Which one? */
  112.          case ENTER :                           /* Selects bar pos */
  113.          case BOTH_MOUSE_KEY :
  114.             return(ttmp[menu->bar_pos].select_key);
  115.          case RITE_MOUSE_KEY :
  116.             if (menu->wnd_pos == 0) break;
  117.             menu->bar_pos = menu->wnd_pos = 0;
  118.             change_menu(menu);
  119.             ttmp = stmp[0];
  120.             max_bars = get_max_bars(ttmp);
  121.             break;
  122.          case LEFT_MOUSE_KEY :
  123.             get_mpos(&row, &col, &bstatus);
  124.             if (row == twnd->wnd->urow+1) {   /* Select row? */
  125.                 /* If hot spot */
  126.                if (search_mouse_select(menu, col)) {
  127.                   change_bar_pos(menu,crnt_bar);   /* Change */
  128.                   /* return */
  129.                   return(ttmp[menu->bar_pos].select_key);
  130.                }
  131.                else {
  132.                   if (col == twnd->wnd->ucol) { /* Up arrow? */
  133.                      menu->wnd_pos--; /* Decrement menu index */
  134.                      if (menu->wnd_pos < 0)  /* Check if okay */
  135.                         /* No - last menu */
  136.                         menu->wnd_pos = max_menus;
  137.                      menu->bar_pos = 0;      /* First bar pos */
  138.                      change_menu(menu);          /* Next menu */
  139.                      /* Address new menu */
  140.                      ttmp = stmp[menu->wnd_pos];
  141.                      /* # bars new menu */
  142.                      max_bars = get_max_bars(ttmp);
  143.                   }
  144.                   else {                        /* Down arrow */
  145.                      if (col == twnd->wnd->lcol) {
  146.                         menu->wnd_pos++;
  147.                         if (stmp[menu->wnd_pos] == NULL)
  148.                            menu->wnd_pos = 0;
  149.                         menu -> bar_pos  = 0;
  150.                         change_menu(menu);
  151.                         ttmp = stmp[menu->wnd_pos];
  152.                         max_bars = get_max_bars(ttmp);
  153.                      }
  154.                   }
  155.                }
  156.             }
  157.             break;
  158.          case LEFTARROW :                       /* Prev bar pos */
  159.          case SHFTTAB :
  160.              menu->bar_pos--;
  161.              if (menu->bar_pos < 0)             /* Check if < 0 */
  162.                 menu->bar_pos = max_bars;     /* Set to max bar */
  163.              change_bar_pos(menu, crnt_bar);  /* Change bar pos */
  164.              break;
  165.          case RITEARROW :                  /* Next bar position */
  166.          case TAB :
  167.              menu->bar_pos++;                   /* Bump & check */
  168.              if (ttmp[menu->bar_pos].select_key == 0)
  169.                  menu->bar_pos = 0;      /* First one if at end */
  170.              change_bar_pos(menu, crnt_bar);     /* Change bars */
  171.              break;
  172.          case UPARROW :                            /* Prev Menu */
  173.          case PGUP:
  174.              if (max_menus == 0) break;
  175.              menu->wnd_pos--;           /* Decrement menu index */
  176.              if (menu->wnd_pos < 0) menu->wnd_pos = max_menus;
  177.              menu->bar_pos = 0;       /* Set bar index to first */
  178.              change_menu(menu);             /* Put out new menu */
  179.              ttmp = stmp[menu->wnd_pos];    /* Address new menu */
  180.              max_bars = get_max_bars(ttmp); /* Count selections */
  181.              break;
  182.          case DOWNARROW :                          /* Next menu */
  183.          case PGDN:
  184.              if (max_menus == 0) break;
  185.              menu->wnd_pos++;                /* Bump menu index */
  186.              if (stmp[menu->wnd_pos] == NULL)  /* See if at end */
  187.                  menu->wnd_pos = 0;         /* And set to first */
  188.              menu->bar_pos = 0;            /* First bar of menu */
  189.              change_menu(menu);             /* Put out new menu */
  190.              ttmp = stmp[menu->wnd_pos];    /* Address new menu */
  191.              max_bars = get_max_bars(ttmp);/* Count the selects */
  192.              break;
  193.          case HOME :                              /* First menu */
  194.          case ESC  :
  195.              if (menu->wnd_pos == 0) break;
  196.              menu->bar_pos = menu->wnd_pos = 0;
  197.              change_menu(menu);
  198.              ttmp = stmp[0];
  199.              max_bars = get_max_bars(ttmp);
  200.              break;
  201.          case END:                                 /* Last Menu */
  202.              if (menu->wnd_pos == max_menus) break;
  203.              menu->bar_pos = 0;
  204.              menu->wnd_pos = max_menus;
  205.              change_menu(menu);
  206.              ttmp = stmp[menu->wnd_pos];
  207.              max_bars = get_max_bars(ttmp);
  208.              break;
  209.          default :
  210.              if (search_menu(menu, ch)) { /* Search for select match */
  211.                 if (crnt_wnd != menu->wnd_pos) { /* In another menu? */
  212.                    change_menu(menu);            /* Put out new menu */
  213.                    ttmp = stmp[menu->wnd_pos];   /* Address new menu */
  214.                    return(ttmp[menu->bar_pos].select_key); /* Return */
  215.                 }
  216.                 if (crnt_bar != menu->bar_pos) { /* Same menu,dif bar */
  217.                    change_bar_pos(menu, crnt_bar);    /* Chg bar pos */
  218.                    return(ttmp[menu->bar_pos].select_key); /* Return */
  219.                 }
  220.                 else                   /* Must be crnt bar so return */
  221.                    return(ttmp[menu->bar_pos].select_key);
  222.              }
  223.       }
  224.    }
  225. #ifndef __TURBOC__
  226.    return 0;
  227. #endif
  228. }
  229.  
  230. /***********************************************************/
  231. /*                       Change_Menu                       */
  232. /*                                                         */
  233. /* When invoked puts menu pointed to by menu->wnd_pos in   */
  234. /* the window.  Bar position is determined by menu->bar_pos*/
  235. /***********************************************************/
  236.  
  237. static void change_menu(TMNUTYPE *menu) {
  238.  
  239.    int      tcv1, col, length;
  240.    TMNUFLDS *ttmp, **stmp;
  241.    MENU_WND *twnd;
  242.  
  243.     twnd = &menu->twnd;
  244.     stmp = (TMNUFLDS **) menu->tlist;
  245.     ttmp = stmp[menu->wnd_pos];
  246.     if (mpresent) hide_mouse();
  247.     clr_wnd(twnd->wnd, 1);
  248.     for (tcv1 = 0; ttmp[tcv1].select_key != (char) NULL; tcv1++)
  249.         wputs(twnd->wnd, ITEMROW, ttmp[tcv1].select_col, ttmp[tcv1].item);
  250.     col = ttmp[menu->bar_pos].select_col;
  251.     length = strlen(ttmp[menu->bar_pos].item);
  252.     w_chg_attr(twnd->wnd,ITEMROW, col, twnd->cfclr, twnd->cbclr, length);
  253.     if (mpresent) show_mouse();
  254. }
  255.  
  256. /***********************************************************/
  257. /*                         Search_Menu                     */
  258. /*                                                         */
  259. /* Searches thru all menus looking for a select_key match  */
  260. /* with keyboard input.  All characters are converted to   */
  261. /* upper case.  Returns non-zero if found.  Zero if not    */
  262. /* found.  If a match is found the menu index and bar index*/
  263. /* are changed to point to the selected item.              */
  264. /***********************************************************/
  265.  
  266. static int search_menu(TMNUTYPE *menu, int select_char) {
  267.  
  268.    TMNUFLDS *ttmp, **stmp;                 /* Menu Pointers */
  269.    int      tcv1, tcv2, ch;                /* Index variables */
  270.  
  271.    stmp = (TMNUFLDS **) menu->tlist;  /* Address menu lists */
  272.    select_char = toupper(select_char); /* Uppercase keybd input */
  273.    for (tcv1 = 0; stmp[tcv1] != NULL; tcv1++) { /* Get the menu list */
  274.        ttmp = stmp[tcv1];         /* One menu list at a time */
  275.        for (tcv2 = 0; ttmp[tcv2].select_key != (char) NULL; tcv2++) {
  276.            /* Uppercase select_key */
  277.            ch = (char) toupper(ttmp[tcv2].select_key);
  278.            if (ch == select_char) {             /* Do they match ? */
  279.               menu->bar_pos = tcv2;               /* Set bar index */
  280.               menu->wnd_pos = tcv1;              /* Set menu index */
  281.               return(1);                            /* Return TRUE */
  282.            }
  283.        }
  284.    }
  285.    return (0);                                       /* No matches */
  286. }
  287.  
  288. /**********************************************************/
  289. /*                   Search_Mouse_Select                  */
  290. /*                                                        */
  291. /* Runs through all items in a menu to determine if the   */
  292. /* rat was on the item.  If a match is found the bar index*/
  293. /* is updated to reflect the selected item and we return  */
  294. /* a non-zero return code to indicate a match was found.  */
  295. /**********************************************************/
  296.  
  297. static int search_mouse_select(TMNUTYPE *menu, int col) {
  298.  
  299.    MENU_WND *twnd;
  300.    TMNUFLDS *ttmp, **stmp;
  301.    int      tcv, item_len, item_col;
  302.  
  303.    twnd = &menu->twnd;                 /* Establish Addressability */
  304.    stmp = (TMNUFLDS **) menu->tlist;
  305.    ttmp = stmp[menu->wnd_pos];
  306.  
  307.    /* If inside the window determine column in the window */
  308.    if (col > twnd->wnd->ucol) col -= twnd->wnd->ucol;
  309.    else return(0);              /* Otherwise not in window so exit */
  310.    /* Search thru all items in list */
  311.    for (tcv = 0; ttmp[tcv].select_key != 0; tcv++) {
  312.         /* Get items column */
  313.         item_col = ttmp[tcv].select_col;
  314.         /* Determine its length on the screen */
  315.         item_len = (item_col + strlen(ttmp[tcv].item)) - 1;
  316.         /* If mouse on the item */
  317.         if (col >= item_col && col <= item_len) {
  318.            menu->bar_pos = tcv;               /* Set the bar index */
  319.            return(1);                               /* Return True */
  320.         }
  321.    }
  322.    return(0);                                    /* No match found */
  323. }
  324.  
  325. /**********************************************************/
  326. /*                    Change_Bar_Pos                      */
  327. /*                                                        */
  328. /* Changes the bar position in the window by changing the */
  329. /* attribute of the current bar to normal window attribute*/
  330. /* and changing the attribute of the new item to the color*/
  331. /* specified for bar color.  Got it.  Okay, test in five  */
  332. /* minutes!                                               */
  333. /**********************************************************/
  334.  
  335. static void change_bar_pos(TMNUTYPE *menu, int crnt_bar) {
  336.  
  337.    int      col, length;
  338.    TMNUFLDS *ttmp, **stmp;
  339.    MENU_WND *twnd;
  340.  
  341.    twnd = &menu->twnd;                 /* Establish addressability */
  342.    stmp = (TMNUFLDS **) menu->tlist;
  343.    ttmp = stmp[menu->wnd_pos];
  344.    if (mpresent) hide_mouse(); /* If rat home hide from neighbors! */
  345.  
  346.    /* Get len and col of item on scrn and change color attribute */
  347.    length = strlen(ttmp[crnt_bar].item);
  348.    col    = ttmp[crnt_bar].select_col;
  349.    w_chg_attr(twnd->wnd,ITEMROW,col,twnd->fcolor,twnd->bcolor,length);
  350.  
  351.    /* Change new item color attribute */
  352.    length = strlen(ttmp[menu->bar_pos].item);
  353.    col    = ttmp[menu->bar_pos].select_col;
  354.    w_chg_attr(twnd->wnd,ITEMROW,col, twnd->cfclr, twnd->cbclr,length);
  355.  
  356.    if (mpresent) show_mouse();   /* Finally turn back on the mouse */
  357. }
  358.  
  359. /**********************************************************/
  360. /*                      Get_Max_Bars                      */
  361. /*                                                        */
  362. /* Used to count how many selections for a given menu.    */
  363. /**********************************************************/
  364.  
  365. static int get_max_bars(TMNUFLDS *ttmp) {
  366.  
  367.     int i;
  368.  
  369.     for (i = 0; ttmp[i].select_key != 0; i++); i--;
  370.     return(i);
  371. }
  372.